/*global UE, UI, jQuery, $, escape, unescape */
/*jslint devel: true, browser: true, undef: true, sloppy: true, regexp: true, plusplus: true,
vars: true, nomen: true, white: true, maxlen: 150, indent: 4 */
////////////////////  UI Library  ////////////////////
//Global Variable
var UI = UI || {};

//temp
UI.temp = UI.temp || {};

//config
UI.config = UI.config || {};

//rootElem
UI.rootElem = document.compatMode && document.compatMode === 'CSS1Compat' ? document.documentElement : document.body;
jQuery(function () {  //document.body maybe not ready when this js running.
	UI.rootScrollingElem = (UE.ua.isWebKit) ? document.body : UI.rootElem;
});

//tab
UI.tab = {};

//mask
//UI.mask.show();
//UI.mask.show(fn);
//UI.mask.hide();
//UI.mask.hide(fn);
UI.mask = {
	isReady: false,
	isVisible: false,
	jSelect: [],
	_ini: function () {
		if (!this.isReady) {
			this.jMask = jQuery('<div class="cmMask"></div>').appendTo(document.body);
			jQuery(window).resize(function (){
				if (UI.mask.isVisible) {
					UI.mask._pos();
				}
			});
			this.isReady = true;
		}
	},
	_pos: function () {
		this.jMask.css({
			width: UI.rootElem.scrollWidth + 'px',
			height: UI.rootElem.scrollHeight + 'px'
		});
	},
	pos: function () {
		this._pos();
	},
	show: function (callback) {
		if (UI.mask.isVisible) {return false; }
		this._ini();
		this._pos();
		this._hideSelect();
		this.jMask.css('visibility', 'visible');
		this.isVisible = true;
		if (jQuery.isFunction(callback)) {callback(); }
	},
	hide: function (callback) {
		if (!UI.mask.isVisible) {return false; }
		this.jMask.css({
			visibility: 'hidden',
			width: '0',
			height: '0'
		});
		this._showSelect();
		this.isVisible = false;
		if (jQuery.isFunction(callback)) {callback(); }
	},
	_hideSelect: function () {
		if (UE.ua.isIE6) {
			this.jSelect = jQuery('select').not('.cmDialogReady select');
			this.jSelect.css('visibility', 'hidden');
		}
	},
	_showSelect: function () {
		if (UE.ua.isIE6) {
			this.jSelect.css('visibility', 'visible');
		}
	}
};

//dialog
//UI.dialog.open('#id');
//UI.dialog.open('.foo .bar');
//UI.dialog.open({s: '#id', callback: fn});
//UI.dialog.close();
//UI.dialog.close({callback: fn});
UI.dialog = {
	isReady: false,  //if .ini() is ready
	isVisible: false,
	isTiming: false,  //for autoClose
	jContent: null,
	timer: null,
	queue: [],
	cfgCurrent: null,  //temp var
	cfgDefault: {
		s: null,
		j: null,
		//callbackWhenOpen: null,
		//callbackWhenClose: null,
		closeBtn: true,
		autoClose: false,
		autoCloseDelay: 3000
	},
	ini: function () {
		var jDialog = jQuery('.cmDialog');
		jDialog.appendTo(document.body).addClass('cmDialogReady').removeClass('cmDialog');
	},
	open: function (arg) {
		if (this._handleCfg(arg)) {
			this._ini();
			this._iniCloseBtn();
			this._setAutoClose();
			this._open(this.cfgCurrent.j);
		}
	},
	close: function () {
		//if (this.isTiming) {return false; }
		if (this.isTiming) {
			clearTimeout(this.timer);
			this.isTiming = false;
		}
		//var j = jQuery(s);
		this._hide(this.queue.shift());
		if (this.queue.length === 0) {
			UI.mask.hide();
		} else {
			this._pos(this.queue[0]);
		}
		UE.log(this.queue);
	},
	switchTo: function (arg) {
		if (this._handleCfg(arg)) {
			this._hide(this.queue.shift());
			this._ini();
			this._iniCloseBtn();
			this._open(this.cfgCurrent.j);
		}
	},
	_iniCloseBtn: function () {
		var j = this.cfgCurrent.j;
		if (this.cfgCurrent.closeBtn && !j.has('a.close-dialog').length) {
			var jCloseBtn = jQuery('<a class="close-dialog icon" href="#close-dialog"></a>').appendTo(j);
			jCloseBtn.click(function () {
				//alert('close');
				UI.dialog.close(this);
				this.blur();
				return false;
			});
		}
	},
	_setAutoClose: function () {
		var j = this.cfgCurrent.j;
		if (this.cfgCurrent.autoClose) {
			this.isTiming = true;
			this.timer = setTimeout(function () {
				UI.dialog.isTiming = false;
				clearTimeout(UI.dialog.timer);
				UI.dialog.close(j);
			}, this.cfgCurrent.autoCloseDelay);
		}
	},
	_open: function (j) {
		if (this.queue.length === 0) {
			UI.mask.show();
			this.queue.unshift(j);
			this._pos(j);
		} else {
			this._hide(this.queue[0]);
			this.queue.unshift(j);
			this._pos(j);
		}
		UE.log(this.queue);
	},
	_handleCfg: function (arg) {
		var cfg = {};
		this.cfgCurrent = {};
		if (typeof arg === 'string' && arg) {
			cfg.s = arg;
			cfg.j = jQuery(arg);
		} else if (!jQuery.isEmptyObject(arg) && jQuery.isPlainObject(arg) && arg.s) {
			cfg = arg;
			cfg.j = jQuery(arg.s);
		}
		//UE.log(cfg);
		if (!jQuery.isEmptyObject(cfg) && cfg.j.hasClass('cmDialogReady')) {
			this.cfgCurrent = {};
			jQuery.extend(this.cfgCurrent, this.cfgDefault);
			jQuery.extend(this.cfgCurrent, cfg);
			//UE.log(this.cfgCurrent);
			return true;
		} else {
			return false;
		}
	},
	_ini: function () {
		if (!this.isReady) {
			//jQuery(window).resize(function (){
			//	if (UI.dialog.jContent) {UI.dialog.pos(); }
			//});
			this.isReady = true;
		}
	},
	_hide: function (j) {
		//var jDialog = j || this.queue[0] || [];
		if (j && j.length) {
			j.closest('.cmDialogReady').css({left:'-999px',top:'-999px'});
		}
		//UI.dialog.jContent = null;
		//UI.mask.hide();
	},
	_pos: function (j) {
		var l = (UI.rootElem.clientWidth - j.outerWidth())/2;
		var t = (UI.rootElem.clientHeight * 0.95 - j.outerHeight())/2;
		l = (l < 5) ? 5 : l;
		t = (t < 5) ? 5 : t;
		j.css({
			left: l + (document.documentElement.scrollLeft || document.body.scrollLeft) + 'px',
			top: t + (document.documentElement.scrollTop || document.body.scrollTop) + 'px'
		});
	}
};

//alert
//UI.alert.open('Some info.');
//UI.alert.open({type: 'error', msg: 'Something wrong.'});
UI.alert = {
	isReady: false,
	cfgCurrent: null,
	cfgDefault: {
		type: 'normal',
		msg: 'MsgTxt'
	},
	className: 'cmDialogReady alert-box',
	ini: function () {
		if (!this.isReady) {
			var html = [
				'<div class="' + this.className + '">',
					'<div class="alert-box-inner clearfix">',
						'<div class="icon"></div>',
						'<div class="text"></div>',
					'</div>',
				'</div>'
			].join('');
			this.jAlertBox = jQuery(html).appendTo(document.body);
			this.jTxtWrapper = this.jAlertBox.find('.text');
			this.isReady = true;
		} else {
			this.clear();
		}
	},
	clear: function () {
		this.jAlertBox.attr('class', this.className);
		this.jTxtWrapper.text('');
	},
	open: function (arg) {
		this.handleCfg(arg);
		if (this.cfgCurrent) {
			this.ini();
			this.jAlertBox.addClass(this.cfgCurrent.type);
			this.jTxtWrapper.html(this.cfgCurrent.msg);
			UI.dialog.open({
				//closeBtn: false,
				autoClose: true,
				autoCloseDelay: (this.cfgCurrent.type === 'success') ? 3000 : 8000,
				s: UI.alert.jAlertBox
			});
		}
	},
	handleCfg: function (arg) {
		var cfg = {};
		this.cfgCurrent = null;
		if (typeof arg === 'string' && arg) {
			cfg.msg = arg;
		} else if (!jQuery.isEmptyObject(arg) && jQuery.isPlainObject(arg)) {
			cfg = arg;
		}
		if (!jQuery.isEmptyObject(cfg)) {
			this.cfgCurrent = {};
			jQuery.extend(this.cfgCurrent, cfg);
		}
	}
};

//loading
//UI.loading.show();
//UI.loading.hide();
UI.loading = {
	isReady: false,
	isVisible: false,
	jSelect: [],
	ini: function () {
		if (!this.isReady) {
			this.jLoading = jQuery('<div class="cmLoading"></div>').appendTo(document.body);
			jQuery(window).resize(function (){
				if (UI.loading.isVisible) {
					UI.loading._pos();
				}
			});
			this.isReady = true;
		}
	},
	_pos: function () {
		var l = (UI.rootElem.clientWidth - this.jLoading.outerWidth())/2;
		var t = (UI.rootElem.clientHeight * 0.95 - this.jLoading.outerHeight())/2;
		l = (l < 0) ? 0 : l;
		t = (t < 0) ? 0 : t;
		this.jLoading.css({
			left: l + (document.documentElement.scrollLeft || document.body.scrollLeft) + 'px',
			top: t + (document.documentElement.scrollTop || document.body.scrollTop) + 'px'
		});
	},
	show: function () {
		if (this.isVisible) {return false; }
		this.ini();
		this._hideSelect();
		this._pos();
		this.isVisible = true;
	},
	hide: function () {
		if (!this.isVisible) {return false; }
		this.jLoading.css({left:'-999px',top:'-999px'});
		this._showSelect();
		this.isVisible = false;
	},
	_hideSelect: function () {
		if (UE.ua.isIE6) {
			this.jSelect = jQuery('select');
			this.jSelect.css('visibility', 'hidden');
		}
	},
	_showSelect: function () {
		if (UE.ua.isIE6) {
			this.jSelect.css('visibility', 'visible');
		}
	}
};

//placeholder
//UI.placeholder.ini();
//UI.placeholder.hide(s|e|j);  //to avoid submit placeholder as data
//UI.placeholder.show(s|e|j);  //show placeholder manually
UI.placeholder = {
	ini: function () {
		var jInput = jQuery('input:text.cmPlaceholder, textarea.cmPlaceholder');
		jInput.each(function () {
			var sTitle = this.title;
			if (sTitle) {
				var jThis = jQuery(this);
				jThis.data('placeholderTxt', sTitle).removeAttr('title');
				if (!this.value || this.value === jThis.data('placeholderTxt')) {  //handle autocomplete and multiple ini.
					this.value = sTitle;
					jThis.addClass('cmPlaceholderBlur');
				}
				UI.placeholder._bind(this);
			}
		});
	},
	_bind: function (e) {
		jQuery(e).focus(function () {
			var jThis = jQuery(this);
			if (this.value === jThis.data('placeholderTxt')) {
				this.value = '';
				jThis.removeClass('cmPlaceholderBlur');
			}
		}).blur(function () {
			var jThis = jQuery(this);
			//UE.log('blur: ' + this.value);
			//UE.log('blur: ' + jThis.data('placeholderTxt'));
			if (!this.value) {
				this.value = jThis.data('placeholderTxt');
				jThis.addClass('cmPlaceholderBlur');
			}
		});
	},
	hide: function (s) {
		var j = s ? jQuery(s) : [];
		if (j.length) {
			var jInput = j.hasClass('cmPlaceholder') ? j : j.find('.cmPlaceholder');
			jInput.each(function () {
				jQuery(this).triggerHandler('focus');
			});
		}
	},
	show: function (s) {
		var j = s ? jQuery(s) : [];
		if (j.length) {
			var jInput = j.hasClass('cmPlaceholder') ? j : j.find('.cmPlaceholder');
			jInput.each(function () {
				jQuery(this).triggerHandler('blur');
			});
		}
	},
	updateTxt: function (s, sTxt) {
		var j = s ? jQuery(s) : [];
		if (j.length && typeof sTxt === 'string') {
			var jInput = j.hasClass('cmPlaceholder') ? j : j.find('.cmPlaceholder');
			jInput.each(function () {
				var jItem = jQuery(this);
				var sOldTxt = jItem.data('placeholderTxt');
				jItem.data('placeholderTxt', sTxt);
				if (this.value === sOldTxt) {
					this.value = sTxt;
				}
			});
		}
	}
};

//hoverClass
//UI.hoverClass.ini('css selector');
UI.hoverClass = {
	ini: function (s) {
		if (UE.ua.isIE6 && s) {
			this._bind(s);
		}
	},
	_bind: function (s) {
		jQuery(s).hover(function () {
			jQuery(this).addClass('hover');
		}, function () {
			jQuery(this).removeClass('hover');
		});
	}
};

//blurLink
//UI.blurLink.ini();
UI.blurLink = {
	ini: function () {
		this.jElem = jQuery('a[href]');
		this._bind();
	},
	_bind: function () {
		this.jElem.live('click', function () {
			this.blur();
		});
	}
};

//rowSelect
//UI.rowSelect.ini();
UI.rowSelect = {
	ini: function () {
		this.jElem = jQuery('tr.cmRowSelectable, li.cmRowSelectable');
		this._bind();
		var jRadio = this.jElem.find('input:radio:checked');
		if (jRadio.length) {this.radioOpenTarget(jRadio); }
	},
	_bind: function () {
		var _this = this;
		this.jElem.live('click', function () {
			var jThis = jQuery(this);
			if (!jThis.hasClass('selected')) {
				var jRadio = jThis.find('input:radio');
				var jSiblings = jThis.closest('form').find('.cmRowSelectable');
				jSiblings.removeClass('selected');
				jThis.addClass('selected');
				jRadio.attr('checked', 'checked');
				_this.radioOpenTarget(jRadio);
			}
		});
	},
	radioOpenTarget: function (jRadio) {
		//open target
		if (jRadio.length) {
			jRadio.each(function () {
				var sTarget = this.getAttribute('rel');
				if (sTarget) {
					UI.rowSelect._openTarget(sTarget);
					UE.log('radioOpenTarget: ' + sTarget);
				}
			});
		}
	},
	iniForm: function (s) {
		var jForm = jQuery(s);
		var jRadio = jForm.find('.cmRowSelectable input:radio:checked');
		var jRow = jForm.find('tr.cmRowSelectable, li.cmRowSelectable');
		if (jRadio.length > 1) {  //fix bug: more than one radio checked after ajax update @ ie
			var jFirstRadio = jRadio.eq(0);
			jRadio.removeAttr('checked');
			jFirstRadio.attr('checked', 'checked');
			jRadio = jFirstRadio;
		}
		jRow.removeClass('selected');
		jRadio.closest('.cmRowSelectable').addClass('selected');
		this.radioOpenTarget(jRadio);
	},
	_openTarget: function (s) {
		if (s) {
			var a = s.split('.');
			var jTarget = jQuery(a[0]);
			if (jTarget.length) {
				var jSiblings = jTarget.siblings('.detail-box');
				var sClass = a[1];
				jSiblings.hide();
				if (sClass) {
					jTarget.attr('class', sClass + ' detail-box');
				}
				jTarget.show();
			}
		}
	}
};

//scrollTo
UI.scrollTo = function (s, fn) {
	if (s && typeof s === 'string') {
		var j = jQuery(s);
		if (j.length) {
			var top = j.offset().top;
			//UE.log('scrollTo: ' + top);
			var duration = 300;
			jQuery(UI.rootScrollingElem).animate({
				scrollTop: top
			}, duration, 'swing', fn);
		}
	}
};


//SingleTab
UI.SingleTab = function(tag, content, args) {
	this.tag = tag;
	this.content = content;
	this.statusTag = false;
	this.statusCon = false;
	this.sets = args || {};
	this.ini();
};

UI.SingleTab.prototype = {
	show: function() {
		this.content.show();
		this.tag.addClass("active");
		if (this.sets.shown) {
			this.sets.shown(this);
		}
	},
	hide: function() {
		this.content.hide();
		this.tag.removeClass("active");
		if (this.sets.hidden) {
			this.sets.hidden(this);
		}
	},
	toggle: function() {
		if (this.statusTag || this.statusCon) {
			this.show();
		} else {
			this.hide();
		}
	},
	run: function() {
		var that = this;
		clearTimeout(this.timer);
		this.timer = setTimeout(function() { that.toggle(); }, 100);
	},
	bind: function() {
		var that = this;
		this.tag.hover(function() {
			that.statusTag = true;
			that.run();
		}, function() {
			that.statusTag = false;
			that.run();
		});
		this.content.hover(function() {
			that.statusCon = true;
			that.run();
		}, function() {
			that.statusCon = false;
			that.run();
		});
	},
	config: function() {
		this.content.hide();
	},
	ini: function() {
		this.config();
		this.bind();
	}
};

//Carousel
UI.Carousel = function(container, args) {
	this.content = container;
	this.items = container.children();
	this.params = {
		type: "h",
		unit: 1,
		speed: "slow",
		position: 0
	};
	if (args) {
		jQuery.extend(this.params, args);
	}
	this.ini();
};

UI.Carousel.prototype = {
	move: function() {
		var that = this, css = {};
		css[this.params.cssName] = "-" + this.params.position + "px";
		this.content.animate(css, this.params.speed, function() {
			that.complete();
		});
	},
	complete: function() {
		if (this.params.position === this.params.scope) {
			this.controlNext.addClass("not");
		} else {
			this.controlNext.removeClass("not");
		}
		if (this.params.position === 0) {
			this.controlPrev.addClass("not");
		} else {
			this.controlPrev.removeClass("not");
		}
		this.status = false;
	},
	next: function() {
		if (this.status || this.params.position === this.params.scope) {return; }
		this.status = true;
		var target = this.params.position + this.params.moveUnit;
		this.params.position = target < this.params.scope ? target : this.params.scope;
		this.move();
	},
	prev: function() {
		if (this.status || this.params.position === 0) {return; }
		this.status = true;
		var target = this.params.position - this.params.moveUnit;
		this.params.position = target > 0 ? target : 0;
		this.move();
	},
	reset: function() {
		this.content.stop().css({
			top: 0,
			left: 0
		});
		this.params.position = 0;
		this.controlPrev.addClass("not");
		this.controlNext.removeClass("not");
		this.status = false;
	},
	bind: function() {
		var that = this;
		this.controlNext.click(function() {
			that.next();
		});
		this.controlPrev.click(function() {
			that.prev();
		});
	},
	create: function() {
		var conWidth,
			conHeight,
			html = [
				"<div class='carousel-wrap' style='width:" + this.content.width() + "px;height:" + this.content.height() + "px;'>",
					"<div class='carousel-content' style='position:relative;width:" + this.content.width() + "px;height:" + this.content.height() + "px;overflow:hidden;'></div>",
					"<div class='carousel-control'>",
						"<span class='prev not'><span class='prev-s'></span></span>",
						"<span class='next'><span class='next-s'></span></span>",
					"</div>",
				"</div>"
			].join('');
		if (this.params.type === "h") {
			conWidth = this.items.width() * this.items.length + "px";
			conHeight = "100%";
		} else {
			conWidth = "100%";
			conHeight = this.items.height() * this.items.length + "px";
		}
		this.content.wrap(html).css({
			position: "absolute",
			top: 0,
			left: 0,
			width: conWidth,
			height: conHeight,
			overflow: "visible"
		});
		this.wrap = this.content.parents(".carousel-wrap");
		this.canvas = this.content.parent();
		this.controlNext = this.wrap.find(".carousel-control .next");
		this.controlPrev = this.wrap.find(".carousel-control .prev");
	},
	config: function() {
		if (this.params.type === "h") {
			this.params.cssName = "left";
			this.params.scope = this.content.width() - this.canvas.width();
			this.params.moveUnit = this.params.unit > 0 ? this.items.width() * this.params.unit : this.canvas.width();
		} else {
			this.params.cssName = "top";
			this.params.scope = this.content.height() - this.canvas.height();
			this.params.moveUnit = this.params.unit > 0 ? this.items.height() * this.params.unit : this.canvas.height();
		}
	},
	ini: function() {
		if (this.params.type === "h") {
			if (this.content.width() >= this.items.width() * this.items.length) {return; }
		} else {
			if (this.content.height() >= this.items.height() * this.items.length) {return; }
		}
		this.create();
		this.config();
		this.bind();
	}
};

//ContentScroll
UI.ContentScroll = function(container, args) {
	this.content = container;
	this.items = container.children();
	this.params = {
		type: 'h',
		speed: 250
	};
	this.position = {
		top: 0,
		left: 0
	};
	if (args) {
		jQuery.extend(this.params, args);
	}
	this.ini();
};

UI.ContentScroll.prototype = {
	move: function() {
		var that = this;
		this.content.animate(this.params.css, this.params.duration, function() {
			that.complete();
		});
	},
	complete: function() {
		this.position = this.content.position();
		var status = this.params.type === 'h' ?
			{ prev: this.position.left === 0, next: Math.abs(this.position.left) === this.params.scope } :
			{ prev: this.position.top === 0, next: Math.abs(this.position.top) === this.params.scope };
		if (status.prev) {
			this.controlPrev.addClass('not');
		}
		if (status.next) {
			this.controlNext.addClass('not');
		}
	},
	next: function() {
		this.params.css = {};
		this.params.css[this.params.cssName] = '-' + this.params.scope + 'px';
		this.params.duration = Math.floor((this.position[this.params.cssName] + this.params.scope) / this.params.speed * 1000);
		this.controlPrev.removeClass('not');
		this.move();
	},
	prev: function() {
		this.params.css = {};
		this.params.css[this.params.cssName] = 0;
		this.params.duration = Math.floor(Math.abs(this.position[this.params.cssName]) / this.params.speed * 1000);
		this.controlNext.removeClass('not');
		this.move();
	},
	reset: function(style) {
		if(!this.controlPrev){return;};
		var posName = this.params.type === 'h' ? 'left' : 'top';
		this.position = style || {
			top: 0,
			left: 0
		};
		this.content.stop().css(this.position);
		if (this.position[posName] === 0) {
			this.controlPrev.addClass('not');
			this.controlNext.removeClass('not');
		} else if (this.params.scope === Math.abs(this.content.position()[posName])) {
			this.controlPrev.removeClass('not');
			this.controlNext.addClass('not');
		} else {
			this.controlPrev.removeClass('not');
			this.controlNext.removeClass('not');
		}
	},
	start: function(dir) {
		var fn, that = this;
		if (dir === 'next') {
			if (this.position[this.params.cssName] === this.params.scope) {return; }
			fn = function() { that.next(); };
		} else {
			if (this.position[this.params.cssName] === 0) {return; }
			fn = function() { that.prev(); };
		}
		this.timer = setTimeout(fn, 180);
	},
	stop: function() {
		clearTimeout(this.timer);
		this.content.stop();
		this.complete();
	},
	bind: function() {
		var that = this;
		this.controlNext.hover(function() {
			that.start('next');
		}, function() {
			that.stop();
		});
		this.controlPrev.hover(function() {
			that.start('prev');
		}, function() {
			that.stop();
		});
	},
	create: function() {
		var conWidth = 0,
			conHeight = 0,
			html = [
				'<div class="scroll-wrap" style="width:' + this.content.width() + 'px;height:' + this.content.height() + 'px;">',
					'<div class="scroll-content" style="position:relative;width:100%;height:100%;overflow:hidden;"></div>',
					'<div class="scroll-control">',
						'<span class="prev not"><span class="prev-s"></span></span>',
						'<span class="next"><span class="next-s"></span></span>',
					'</div>',
				'</div>'
			].join("");
		if (this.params.type === 'h') {
			this.items.each(function() {
				conWidth += jQuery(this).width();
			});
			conWidth += 'px';
			conHeight = '100%';
		} else {
			conWidth = '100%';
			this.items.each(function() {
				conHeight += jQuery(this).height();
			});
			conHeight += 'px';
		}
		this.content.wrap(html).css({
			position: 'absolute',
			top: 0,
			left: 0,
			width: conWidth,
			height: conHeight,
			overflow: 'visible'
		});
		this.wrap = this.content.parents('.scroll-wrap');
		this.canvas = this.content.parent();
		this.controlNext = this.wrap.find('.scroll-control .next');
		this.controlPrev = this.wrap.find('.scroll-control .prev');
	},
	config: function() {
		if (this.params.type === 'h') {
			this.params.cssName = 'left';
			this.params.scope = this.content.width() - this.canvas.width();
		} else {
			this.params.cssName = 'top';
			this.params.scope = this.content.height() - this.canvas.height();
		}
	},
	ini: function() {
		var conSize = 0;
		if (this.params.type === 'h') {
			this.items.each(function() {
				conSize += jQuery(this).width();
			});
			if (this.content.width() >= conSize) {return; }
		} else {
			this.items.each(function() {
				conSize += jQuery(this).height();
			});
			if (this.content.height() >= conSize) {return; }
		}
		this.create();
		this.config();
		this.bind();
	}
};

//JQTab
/* 
Interface JQTab {
	function switchTo(index);
	function autoPlay(interval);
	function stopPlay();
}
*/
UI.JQTab = function(contents, args) {
	this.cons = contents;
	this.sets = {
		event: 'click',
		style: 'basic'
	};
	if (args) {
		jQuery.extend(this.sets, args);
	}
	this.controls = [];
	this.ini();
};

UI.JQTab.prototype = {
	basic: function() {
		this.hidden(jQuery(this.cons[this.current]).hide()[0]);
		this.shown(jQuery(this.cons[this.waiting]).show()[0]);
	},
	slide: function() {
		var that = this;
		jQuery(this.cons[this.current]).slideUp(this.sets.speed, function() { that.hidden(this); });
		jQuery(this.cons[this.waiting]).slideDown(this.sets.speed, function() { that.shown(this); });
	},
	fade: function() {
		var that = this;
		jQuery(this.cons[this.current]).fadeOut(this.sets.speed, function() { that.hidden(this); });
		jQuery(this.cons[this.waiting]).fadeIn(this.sets.speed, function() { that.shown(this); });
	},
	hidden: function(o) {
		jQuery(o).removeClass('current').hide();
		if (this.sets.hidden) {
			this.sets.hidden(o);
		}
	},
	shown: function(o) {
		jQuery(o).addClass('current');
		if (this.sets.shown) {
			this.sets.shown(o);
		}
	},
	switchTo: function(index) {
		var that = this;
		if (this.current !== index) {
			this.waiting = index;
			this[this.sets.style]();
			jQuery.each(this.controls, function(key, value) {
				if (that[value + 'Synch']) {
					that[value + 'Synch']();
				}
			});
			this.current = index;
		}
	},
	consIni: function() {
		var index = this.sets.index;
		jQuery.each(this.cons, function(i, o) {
			if (index === i) {
				jQuery(o).show().addClass('current');
			} else {
				jQuery(o).hide().removeClass('current');
			}
		});
	},
	autoPlay: function(interval) {
		var that = this, size = this.cons.length - 1, duration = interval || this.sets.autoPlay, fn =  function() {
			var index = that.current < size ? that.current + 1 : 0;
			that.switchTo(index);
			that.timer = setTimeout(arguments.callee, duration);
		};
		this.timer = setTimeout(fn, duration);
	},
	stopPlay: function() {
		clearTimeout(this.timer);
	},
	tagIni: function() {
		var that = this;
		this.tags.each(function(i) {
			var $this = jQuery(this);
			$this.bind(that.sets.event, function() {
				that.switchTo(i);
				return false;
			});
			if (that.sets.index === i) {
				$this.addClass('current');
			}
		});
		this.controls.push('tag');
	},
	tagSynch: function() {
		jQuery(this.tags[this.current]).removeClass('current');
		jQuery(this.tags[this.waiting]).addClass('current');
	},
	numTagIni: function() {
		var that = this, $ul = jQuery('<ul></ul>'), index = this.sets.index, i = 0, len = this.cons.length;
		this.numTags = [];
		while (i < len) {
			this.numTags.push(jQuery('<li><a href="#">' + i + '</a></li>').appendTo($ul));
			i++;
		}
		jQuery.each(this.numTags, function(key, $item) {
			$item.bind(that.sets.event, function() {
				that.switchTo(key);
				return false;
			});
			if (index === key) {
				$item.addClass('current');
			}
		});
		this.cons.last().after(jQuery('<div class="num-tags"></div>').append($ul));
		this.controls.push('numTag');
	},
	numTagSynch: function() {
		jQuery(this.numTags[this.current]).removeClass('current');
		jQuery(this.numTags[this.waiting]).addClass('current');
	},
	config: function() {
		if (!this.sets.speed) {
			this.sets.speed = !this.sets.style || this.sets.style === 'basic' ? 0 : 'slow';
		}
		this.sets.index = this.sets.index !== undefined ? this.sets.index - 1 : 0;
		this.current = this.sets.index;
		this.waiting = this.sets.index;
		this.consIni();
		if (this.sets.tags) {
			this.tags = this.sets.tags;
			this.tagIni();
		}
		if (this.sets.numTags) {
			this.numTagIni();
		}
		if (this.sets.autoPlay) {
			this.autoPlay();
		}
	},
	ini: function() {
		this.config();
	}
};

//PanoramaPic
UI.PanoramaPic = function(canvas, args) {
	this.canvas = canvas;
	this.sets = {
		src: canvas.attr("data-photo"),
		speed: 100
	};
	if (args) {
		jQuery.extend(this.sets, args);
	}
	this.ini();
};

UI.PanoramaPic.prototype = {
	move: function() {
		var pos = this.frameUnit * this.currentFrame;
		this.canvas.css("backgroundPosition", "-" + pos + "px" + " 0");
	},
	next: function() {
		this.currentFrame = this.currentFrame + 1 === this.frameLength ? 0 : this.currentFrame + 1;
		this.move();
	},
	prev: function() {
		this.currentFrame = this.currentFrame - 1 === 0 ? this.frameLength - 1 : this.currentFrame - 1;
		this.move();
	},
	play: function() {
		if (this.status) {return; }
		var that = this;
		this.status = true;
		if (this.sets.played) {
			this.sets.played(this);
		}
		(function() {
			that.next();
			that.timer = setTimeout(arguments.callee, that.sets.speed);
		}());
	},
	stop: function() {
		clearTimeout(this.timer);
		this.status = false;
	},
	reset: function() {
		this.stop();
		this.canvas.css("background", "url(" + this.sets.src + ") 0 0 no-repeat");
		this.currentFrame = 0;
	},
	controlMove: function() {
		var n = Math.floor((this.controlX - this.controlIniX) / 10 );
		if (n > this.controlMoved) {
			this.next();
			this.controlMoved++;
		} else if (n < this.controlMoved) {
			this.prev();
			this.controlMoved--;
		} else {
			return;
		}
	},
	controlBind: function() {
		var that = this;
		this.canvas.bind({
			mousedown: function(e) {
				that.controlIniX = e.clientX;
				that.stop();
				that.status = false;
				jQuery(this).mousemove(function(event) {
					that.controlX = event.clientX;
					that.controlMove();
				});
				return false;
			},
			mouseup: function() {
				jQuery(this).unbind("mousemove");
				that.controlMoved = 0;
				that.play();
			}
		});
	},
	imgLoad: function() {
		var that = this, img = new Image();
		this.timerImg = setTimeout(function() {
			that.canvas.addClass("loading");
		}, 100);
		img.onload = function() {
			that.imgLoaded(this);
		};
		img.src = this.sets.src;
	},
	imgLoaded: function(img) {
		clearTimeout(this.timerImg);
		this.frameLength = Math.floor(img.width / this.frameUnit);
		this.canvas.removeClass("loading");
		this.canvas.css("background", "url(" + this.sets.src + ") 0 0 no-repeat");
		this.play();
	},
	config: function() {
		var that = this;
		this.frameUnit = this.canvas.width();
		this.currentFrame = 0;
		this.controlBind();
		this.controlMoved = 0;
		if (this.sets.button) {
			this.button = this.sets.button;
			this.button.click(function() {
				if (that.status) {return false; }
				that.imgLoad();
			});
		} else {
			that.imgLoad();
		}
	},
	ini: function() {
		this.config();
	}
};

//Nice Select
/*
Interface NiceSelect {
	function selection(index);
	function toggleOptions();
	function showOptions();
	function hideOptions();
}
*/
UI.NiceSelect = function(select) {
	this.$select = jQuery(select);
	this.$options = this.$select.find('option');
	this.optionCons = [];
	this.niceOptions = [];
	this.niceStatus = false;
	this.ini();
};
UI.NiceSelect.prototype = {
	selection: function(index) {
		this.waiting = index;
		this.$select[0].selectedIndex = index;
		this.controlUpdate();
		this.current = index;
		this.$select.change();
	},
	controlUpdate: function() {
		this.$text.text(this.optionCons[this.waiting]);
		this.niceOptions[this.current].removeClass('current');
		this.niceOptions[this.waiting].addClass('current');
	},
	toggleOptions: function() {
		if (this.niceStatus) {
			this.hideOptions();
		} else {
			this.showOptions();
		}
	},
	showOptions: function() {
		this.$ul.show();
		this.niceStatus = true;
	},
	hideOptions: function() {
		this.$ul.hide();
		this.niceStatus = false;
	},
	createNice: function() {
		var that = this;
		this.$nice = jQuery('<div class="nice-select"></div>');
		this.$text = jQuery('<a href="#" class="a-value"></a>').click(function() {
			that.toggleOptions();
			return false;
		}).appendTo(this.$nice);
		this.$ul = jQuery('<ul style="display:none;"></ul>').hover(function() {
			jQuery(this).addClass('hover');
		}, function() {
			jQuery(this).removeClass('hover');
		}).appendTo(this.$nice);
		jQuery.each(this.$options, function(i, o) {
			var text = jQuery(o).text();
			that.optionCons.push(text);
			that.niceOptions.push(jQuery('<li><a href="#">' + text + '</a></li>').click(function() {
				that.selection(i);
				that.hideOptions();
				return false;
			}).appendTo(that.$ul));
		});
		this.$select.after(this.$nice).hide();
	},
	setDefault: function() {
		this.current = this.$select[0].selectedIndex;
		this.waiting = this.current;
		this.controlUpdate();
	},
	bind: function() {
		var that = this;
		jQuery('body').click(function(e) {
			if (e.target !== that.$select[0]) {
				if (that.niceOptions) {
					that.hideOptions();
				}
			}
		});
	},
	ini: function() {
		this.createNice();
		this.setDefault();
		this.bind();
	}
};

//----------------------------------------
UE.cart.amountBox = {
	ini: function () {
		var j = jQuery('#shopping-cart-table div.amount-box');
		j.each(function () {
			this.objAmountBox = new UE.cart.amountBox.Class(this);
		});
	},
	Class: function (e) {
		this.j = jQuery(e);
		this.jInput = this.j.find('input:text');
		this.min = parseInt(this.jInput.attr('min'), 10) || 0;
		this.max = parseInt(this.jInput.attr('max'), 10);  //may be NaN or 0
		if (isNaN(this.max)) {this.max = Infinity;}
		//this.value = parseInt(this.jInput.val(), 10);
		this.ini();
		//UE.log(this.j);
	}
};
UE.cart.amountBox.Class.prototype = {
	ini: function () {
		this._addCtrl();
		this._bind();
	},
	_addCtrl: function () {
		this.jBtnIncrease = jQuery('<a class="increase" href="#increase">+</a>').appendTo(this.j);
		this.jBtnDecrease = jQuery('<a class="decrease" href="#decrease">-</a>').appendTo(this.j);
	},
	_bind: function () {
		var _this = this;
		this.jBtnIncrease.click(function (e) {
			e.preventDefault();
			_this.jInput.trigger('before-increase');
			_this._mod(1);
		});
		this.jBtnDecrease.click(function (e) {
			e.preventDefault();
			_this.jInput.trigger('before-decrease');
			_this._mod(-1);
		});
	},
	_mod: function (step) {
		this.jInput.trigger('before-change');
		this.value = parseInt(this.jInput.val(), 10);
		if (!this.value) {
			this.value = this.min;
		} else {
			this.value += step;
			if (this.value < this.min) {
				this.value = this.min;
			}
			if (this.value > this.max) {
				this.value = this.max;
			}
		}
		this.jInput.val(this.value);
		this.jInput.trigger('change');
	}
};
